"""
OCR任务处理器 - 从队列中取出任务并进行OCR识别
这个模块负责处理队列中的任务，调用百度OCR识别，然后保存到数据库
"""

# 导入标准库
import asyncio  # 异步IO库
from typing import Optional, Dict  # 类型提示

# 导入项目内部模块
from tools.redis_queue import pop_task_from_queue  # 从队列中取出任务的函数
from tools.ocr import ocr_id_card  # OCR识别函数
from database import get_db  # 数据库会话函数
from models.auth import UserAuth  # 用户认证模型
from sqlalchemy.orm import Session  # SQLAlchemy会话类


async def process_one_task() -> bool:
    """
    处理队列中的一个OCR任务
    
    返回:
        True表示处理成功，False表示没有任务或处理失败
    
    工作流程：
    1. 从队列中取出一个任务
    2. 调用百度OCR识别
    3. 把识别结果保存到数据库
    """
    # 从Redis队列中取出一个任务
    # 如果队列为空，pop_task_from_queue会返回None
    task = pop_task_from_queue()
    
    # 检查是否有任务
    # 如果task是None，说明队列空了，没有任务需要处理
    if task is None:
        # 返回False，表示没有任务处理
        return False
    
    # 从任务数据中提取需要的信息
    # task是一个字典，包含了用户ID、图片信息等
    user_id = task.get('user_id')          # 用户ID
    card_side = task.get('card_side')      # 身份证正反面：'front'或'back'
    image_base64 = task.get('image_base64') # 图片的base64编码
    image_url = task.get('image_url')       # 图片的URL地址（可选）
    
    try:
        # 创建一个数据库会话
        # 数据库会话就像一个连接，用来操作数据库
        # 直接从SessionLocal创建一个会话，而不是使用get_db生成器
        from database import SessionLocal
        db = SessionLocal()
        
        try:
            # 调用百度OCR工具识别身份证
            # ocr_id_card函数会调用百度API，返回识别结果
            # 注意：需要使用await等待异步函数执行完成
            ocr_result = await ocr_id_card(
                image_base64=image_base64,
                image_url=image_url,
                card_side=card_side
            )
            
            # 检查识别是否成功
            # 如果ocr_result是None，说明识别失败了
            if not ocr_result:
                print(f"[OCR处理] 识别失败: 用户{user_id}, {card_side}面")
                
                # 通过 WebSocket 推送失败消息给用户
                try:
                    from tools.websocket_manager import websocket_manager
                    await websocket_manager.send_personal_message({
                        "type": "ocr_failed",
                        "card_side": card_side,
                        "message": "身份证识别失败，请重新上传",
                        "data": {
                            "success": False,
                            "error": "OCR识别失败"
                        }
                    }, user_id)
                    print(f"[OCR处理] WebSocket失败消息已推送给用户 {user_id}")
                except Exception as e:
                    print(f"[OCR处理] WebSocket推送失败: {e}")
                
                # 返回False表示处理失败
                return False
            
            # 打印OCR识别的完整结果，方便查看哪些字段识别出来了
            print(f"[OCR处理] 识别结果详情: {ocr_result}")
            
            # 根据正反面分别处理
            # 如果是正面，保存姓名、身份证号等信息
            if card_side == "front":
                # 查询数据库，看用户是否已经有认证记录
                user_auth = db.query(UserAuth).filter(UserAuth.user_id == user_id).first()
                
                # 如果有记录，就更新；如果没有，就创建新的
                if user_auth:
                    # 更新现有记录的正面信息
                    user_auth.real_name = ocr_result.get("name", "")
                    user_auth.id_card_num = ocr_result.get("id_card_num", "")
                    user_auth.gender = ocr_result.get("gender", "")
                    user_auth.nation = ocr_result.get("nation", "")
                    user_auth.birth = ocr_result.get("birth", "")
                    user_auth.address = ocr_result.get("address", "")
                else:
                    # 创建新的认证记录
                    user_auth = UserAuth(
                        user_id=user_id,
                        real_name=ocr_result.get("name", ""),
                        id_card_num=ocr_result.get("id_card_num", ""),
                        gender=ocr_result.get("gender", ""),
                        nation=ocr_result.get("nation", ""),
                        birth=ocr_result.get("birth", ""),
                        address=ocr_result.get("address", "")
                    )
                    # 添加到数据库会话
                    db.add(user_auth)
                
                # 提交事务，把数据真正保存到数据库
                db.commit()
                # 刷新对象，获取最新的数据（包括自动生成的ID等）
                db.refresh(user_auth)
                
                # 打印保存后的数据，确认已经成功存储
                print(f"[OCR处理] 正面识别成功并保存: 用户{user_id}")
                print(f"[OCR处理] 存储的数据: 姓名={user_auth.real_name}, 身份证号={user_auth.id_card_num}, "
                      f"性别={user_auth.gender}, 民族={user_auth.nation}, "
                      f"出生={user_auth.birth}, 住址={user_auth.address}")
                
                # 通过 WebSocket 推送成功消息给用户
                try:
                    from tools.websocket_manager import websocket_manager
                    await websocket_manager.send_personal_message({
                        "type": "ocr_completed",
                        "card_side": "front",
                        "message": "身份证正面识别完成",
                        "data": {
                            "real_name": user_auth.real_name,
                            "id_card_num": user_auth.id_card_num,
                            "gender": user_auth.gender,
                            "nation": user_auth.nation,
                            "birth": user_auth.birth,
                            "address": user_auth.address,
                            "success": True
                        }
                    }, user_id)
                    print(f"[OCR处理] WebSocket成功消息已推送给用户 {user_id}")
                except Exception as e:
                    # WebSocket推送失败不影响主流程
                    print(f"[OCR处理] WebSocket推送失败: {e}")
                
            else:
                # 处理反面信息
                # 查询用户的认证记录
                user_auth = db.query(UserAuth).filter(UserAuth.user_id == user_id).first()
                
                # 如果已经有记录（说明正面已经上传过），就更新反面信息
                if user_auth:
                    # 更新反面信息：签发机关和有效期
                    user_auth.issuing_authority = ocr_result.get("issuing_authority", "")
                    user_auth.valid_date = ocr_result.get("valid_date", "")
                    # 提交保存
                    db.commit()
                    # 刷新对象
                    db.refresh(user_auth)
                    
                    # 打印保存后的数据
                    print(f"[OCR处理] 反面识别成功并保存: 用户{user_id}")
                    print(f"[OCR处理] 存储的数据: 签发机关={user_auth.issuing_authority}, 有效期={user_auth.valid_date}")
                    
                    # 通过 WebSocket 推送成功消息给用户
                    try:
                        from tools.websocket_manager import websocket_manager
                        await websocket_manager.send_personal_message({
                            "type": "ocr_completed",
                            "card_side": "back",
                            "message": "身份证反面识别完成",
                            "data": {
                                "issuing_authority": user_auth.issuing_authority,
                                "valid_date": user_auth.valid_date,
                                "success": True
                            }
                        }, user_id)
                        print(f"[OCR处理] WebSocket成功消息已推送给用户 {user_id}")
                    except Exception as e:
                        # WebSocket推送失败不影响主流程
                        print(f"[OCR处理] WebSocket推送失败: {e}")
                else:
                    # 如果没有正面记录，提示错误
                    print(f"[OCR处理] 错误: 用户{user_id}尚未上传正面，无法处理反面")
                    
                    # 通过 WebSocket 推送错误消息给用户
                    try:
                        from tools.websocket_manager import websocket_manager
                        await websocket_manager.send_personal_message({
                            "type": "ocr_failed",
                            "card_side": card_side,
                            "message": "请先上传身份证正面",
                            "data": {
                                "success": False,
                                "error": "尚未上传正面，无法处理反面"
                            }
                        }, user_id)
                        print(f"[OCR处理] WebSocket错误消息已推送给用户 {user_id}")
                    except Exception as e:
                        print(f"[OCR处理] WebSocket推送失败: {e}")
                    
                    return False
            
            # 处理成功，返回True
            return True
            
        except Exception as e:
            # 如果处理过程中出错了
            print(f"[OCR处理] 处理任务时出错: {e}")
            import traceback
            traceback.print_exc()
            
            # 回滚事务，撤销刚才的操作
            db.rollback()
            
            # 通过 WebSocket 推送异常消息给用户
            try:
                from tools.websocket_manager import websocket_manager
                await websocket_manager.send_personal_message({
                    "type": "ocr_failed",
                    "card_side": card_side,
                    "message": f"处理过程中出错: {str(e)}",
                    "data": {
                        "success": False,
                        "error": str(e)
                    }
                }, user_id)
                print(f"[OCR处理] WebSocket异常消息已推送给用户 {user_id}")
            except Exception as ws_error:
                print(f"[OCR处理] WebSocket推送失败: {ws_error}")
            
            # 返回False表示失败
            return False
            
        finally:
            # 无论成功还是失败，都要关闭数据库连接
            # finally确保这段代码一定会执行
            db.close()
            
    except Exception as e:
        # 如果创建数据库连接时出错了
        print(f"[OCR处理] 数据库连接失败: {e}")
        # 返回False表示失败
        return False